﻿using Castle.DynamicProxy;
using commonFramwork.Attribute;
using commonFramwork.Enum;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace commonFramwork.Interceptor
{
    /// <summary>
    /// 缓存拦截
    /// </summary>
    public class CacheIntercetor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {

            if (invocation.Method.IsDefined(typeof(CacheAttribute), false))
            {
                //方法名称
                var key = invocation.Method.Name;
                var cachingAttribute = (CacheAttribute)invocation.Method.GetCustomAttributes(typeof(CacheAttribute), false)[0];
                
                //设置不同参数的缓存
                var valkey = GetValueKey(cachingAttribute, invocation);

                if (cachingAttribute.MethodType == CacheMethod.get)
                {

                    try
                    {
                        if (CacheManager.CacheManager.Instance.Exists(key, valkey))
                        {
                            var obj = CacheManager.CacheManager.Instance.Get(key, valkey);
                            invocation.ReturnValue = obj;
                        }
                        else
                        {
                            invocation.Proceed();
                            CacheManager.CacheManager.Instance.Add(key, valkey, invocation.ReturnValue);
                        }
                    }
                    catch (Exception ex)
                    {
                        throw;
                    }
                }
                else if (cachingAttribute.MethodType == CacheMethod.put)
                {
                    try
                    {
                        invocation.Proceed();
                        if (CacheManager.CacheManager.Instance.Exists(key))
                        {
                            if (cachingAttribute.Force)
                            {
                                CacheManager.CacheManager.Instance.Remove(key);
                                CacheManager.CacheManager.Instance.Add(key, valkey, invocation.ReturnValue);
                            }
                            else
                                CacheManager.CacheManager.Instance.Put(key, valkey, invocation.ReturnValue);
                        }
                        else
                            CacheManager.CacheManager.Instance.Add(key, valkey, invocation.ReturnValue);
                    }
                    catch (Exception)
                    {
                        throw;
                    }

                }
                else if (cachingAttribute.MethodType == CacheMethod.remove) //删除缓存
                {
                    try
                    {
                        var removeKeys = cachingAttribute.CorrespondingMethodNames;
                        foreach (var removeKey in removeKeys)
                        {
                            if (CacheManager.CacheManager.Instance.Exists(removeKey))
                                CacheManager.CacheManager.Instance.Remove(removeKey);
                        }
                        invocation.Proceed();
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
            }
            else
            {
                invocation.Proceed();
            }
        }

        /// <summary>
        /// 根据参数生成缓存key
        /// </summary>
        /// <param name="cachingAttribute"></param>
        /// <param name="invocation"></param>
        /// <returns></returns>
        public string GetValueKey(CacheAttribute cachingAttribute, IInvocation invocation)
        {
            switch (cachingAttribute.MethodType)
            {

                case CacheMethod.remove:
                    return null;
                case CacheMethod.get:
                case CacheMethod.put:
                    if (invocation.Arguments != null &&
                        invocation.Arguments.Length > 0)
                    {
                        var sb = new  StringBuilder();
                        var ls = new List<string>();
                        invocation.Arguments.ToList().ForEach((x) =>
                        {
                            ls.Add(x.ToString());
                        });
                        return string.Join("-", ls.ToArray());
                    }
                    else
                    {//没有参数的情况
                        return "NULL";
                    }
                  
                default:
                    throw new InvalidOperationException("无效的缓存方式");
            }
        }

    }
}
